#include "LecteurPhraseSimple.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseSimple::LecteurPhraseSimple(string nomFich) :
	ls(nomFich) {
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::programme() {
// <programme> ::= debut <seqInst> fin FIN_FICHIER
	
	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }
	do {
		inst();
		sauterSymCour(";");
	} while (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="si" ||
                 ls.getSymCour()=="tantque" || ls.getSymCour() == "repeter" ||
                 ls.getSymCour()=="lire" || ls.getSymCour()=="ecrire" ||
                 ls.getSymCour()=="pour");
	// tant que le symbole courant est un debut possible d'instruction...
}


void LecteurPhraseSimple::instLire(){
    if (ls.getSymCour()=="lire"){
        sauterSymCour("lire");
        sauterSymCour("(");
        sauterSymCour("<VARIABLE>");
        sauterSymCour(")");
    }
}

void LecteurPhraseSimple::instEcrire(){
if (ls.getSymCour()=="ecrire"){
        sauterSymCour("ecrire");
        sauterSymCour("(");
        if (ls.getSymCour()=="<CHAINE>")
            sauterSymCour("<CHAINE>");
        else 
            expression();
        sauterSymCour(")");
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::inst() {

    if (ls.getSymCour()=="si")
        instSi();
    else if (ls.getSymCour()=="tantque")
        instTq();
    else if (ls.getSymCour()=="repeter")
        instRepeter();
    else if (ls.getSymCour()=="lire")
        instLire();
    else if (ls.getSymCour()=="ecrire")
        instEcrire();
    else if (ls.getSymCour()=="pour")
        instPour();
    else
        affectation();
}

// si (<expbool>) <seqinst> {sinonsi (<expbool>) <seqinst>} [sinon <seqinst>] finsi
void LecteurPhraseSimple::instSi(){
    if (ls.getSymCour()=="si"){
        sauterSymCour("si");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");
        seqInst();
        while (ls.getSymCour()=="sinonsi"){
            sauterSymCour("sinonsi");
            sauterSymCour("(");
            expBool();
            sauterSymCour(")");
            seqInst();
        }
        if (ls.getSymCour()=="sinon"){
            sauterSymCour("sinon");
            seqInst();
        }
        sauterSymCour("finsi");
    }
}

// tantque (<expbool>) <seqinst> fintantque
void LecteurPhraseSimple::instTq(){
    if (ls.getSymCour()=="tantque"){
        sauterSymCour("tantque");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");
        seqInst();
        sauterSymCour("fintantque");
    }
}

void LecteurPhraseSimple::instPour(){
    if (ls.getSymCour()=="pour"){
        sauterSymCour("pour");
        sauterSymCour("(");
        affectation();
        sauterSymCour(";");
        expBool();
        sauterSymCour(";");
        affectation();
        sauterSymCour(")");
        seqInst();
        sauterSymCour("finpour");
    }
}
void LecteurPhraseSimple::instRepeter(){
    if (ls.getSymCour()=="repeter"){
        sauterSymCour("repeter");
        seqInst();
        sauterSymCour("jusqua");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");
    }
}


////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::affectation() {
// <affectation> ::= <variable> = <expression> 

	sauterSymCour("<VARIABLE>");
        if (ls.getSymCour()=="=")
        {
                sauterSymCour("=");
                expression();
        }
        else if (ls.getSymCour()=="++")
        {
                sauterSymCour("++");
        }
        else if (ls.getSymCour()=="--")
        {
                sauterSymCour("--");
        }
	
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expression() {
// <expression> ::= <terme> { <opAdd> <terme> }
	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-") {
		opAdd();
		terme();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::terme() {
// <expression> ::= <facteur> { <opMult> <facteur> }
	facteur();
	while (ls.getSymCour()=="*" || ls.getSymCour()=="/") {
		opMult();
		facteur();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::facteur() {
// <facteur> ::= <entier>  |  <variable>  |  - <facteur>  |  ( <expression> )
	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
		ls.suivant();
	else if (ls.getSymCour()=="-" || ls.getSymCour()=="non") {
                opUnaire();
		expBool();
	} else if (ls.getSymCour()=="(") {
		ls.suivant();
		expBool();
		sauterSymCour(")");
	} else
		erreur("<facteur>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opAdd()
{
	if (ls.getSymCour()=="+" || ls.getSymCour()=="-" )
		ls.suivant();
	else
		erreur("<opAdd>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opMult()
{
	if (ls.getSymCour()=="*" || ls.getSymCour()=="/" )
		ls.suivant();
	else
		erreur("<opMult>");
}

void LecteurPhraseSimple::opBool(){
        if (ls.getSymCour()=="et" || ls.getSymCour()=="ou" )
		ls.suivant();
	else
		erreur("<opBool>");
}

void LecteurPhraseSimple::expEt(){
    relation();
    while (ls.getSymCour()=="et") {
        opBool();
        relation();
    }
}

void LecteurPhraseSimple::opRel(){
        if (ls.getSymCour()=="==" || ls.getSymCour()=="!=" ||
            ls.getSymCour()==">=" || ls.getSymCour()=="<=" ||
            ls.getSymCour()==">"  || ls.getSymCour()=="<" )
		ls.suivant();
	else
		erreur("<opRel>");
}

void LecteurPhraseSimple::opUnaire(){
        if (ls.getSymCour()=="-" || ls.getSymCour()=="non" )
		ls.suivant();
        else
		erreur("<opUnaire>");
}

void LecteurPhraseSimple::expBool(){
	expEt();
	while (ls.getSymCour()=="ou") {
		opBool();
                expEt();
	}
}

void LecteurPhraseSimple::relation(){
	expression();
	while (ls.getSymCour()=="==" || ls.getSymCour()=="!=" ||
               ls.getSymCour()==">=" || ls.getSymCour()=="<=" ||
               ls.getSymCour()==">"  || ls.getSymCour()=="<" ) {
		opRel();
		expression();
	}
}


////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}
